package com.heima.comment.service.impl;

import com.alibaba.fastjson.JSON;
import com.heima.apis.article.IArticleClient;
import com.heima.apis.user.IUserClient;
import com.heima.comment.pojos.ApComment;
import com.heima.comment.pojos.ApCommentLike;
import com.heima.comment.service.ApCommentService;
import com.heima.comment.vos.ApCommentVo;
import com.heima.common.baiduyun.utils.ExamineUtil;
import com.heima.common.constants.HotArticleConstants;
import com.heima.common.exception.CustomException;
import com.heima.model.article.pojos.ApArticleConfig;
import com.heima.model.comment.dtos.CommentDto;
import com.heima.model.comment.dtos.CommentLikeDto;
import com.heima.model.comment.dtos.CommentSaveDto;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.mess.UpdateArticleMess;
import com.heima.model.user.pojos.ApUser;
import com.heima.utils.thread.AppThreadLocalUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * ClassName: ApCommentServiceImpl
 * Description:
 * date: 2023/8/29 0029 16:17
 *
 * @author zHan
 */
@Service
@Slf4j
@Transactional(rollbackFor = Throwable.class)
public class ApCommentServiceImpl implements ApCommentService {

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private IUserClient userClient;

    @Autowired
    private IArticleClient articleClient;

    @Autowired
    private ExamineUtil examineUtil;

    @Autowired
    private KafkaTemplate<String,String> kafkaTemplate;

    /**
     * 保存评论
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult save(CommentSaveDto dto) {
        // 参数校验
        if (dto == null || dto.getArticleId() == null || StringUtils.isBlank(dto.getContent())) {
            throw new CustomException(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        // 评论内容大于140，报错
        if (dto.getContent().length() > 140) {
            return ResponseResult.errorResult(201, "评论内容不能大于140字");
        }
        // 判断用户是否登录
        ApUser apUser = AppThreadLocalUtil.getUser();
        if (apUser == null) {
            throw new CustomException(AppHttpCodeEnum.NEED_LOGIN);
        }
        // 判断文章是否可以评论
        boolean isComment = checkComment(dto.getArticleId());
        if (!isComment) return ResponseResult.errorResult(201, "该文章不可评论");
        // 根据用户id查询用户信息
        ResponseResult responseResult = userClient.getUserInfo(apUser.getId());
        if (responseResult.getCode().equals(200)) {
            String json = JSON.toJSONString(responseResult.getData());
            ApUser dbUser = JSON.parseObject(json, ApUser.class);
            ApComment apComment = new ApComment();
            // 封装对象
            apComment.setAuthorId(apUser.getId());
            apComment.setAuthorName(dbUser.getName());
            apComment.setEntryId(dto.getArticleId());
            apComment.setType((short) 0);
            apComment.setContent(dto.getContent());
            apComment.setCreatedTime(new Date());
            apComment.setLikes(0);
            apComment.setReply(0);
            apComment.setFlag((short) 0);
            // 对评论内容进行审核
            boolean isSuccess = autoExamineText(dto.getContent());
            if (!isSuccess) return ResponseResult.errorResult(201, "评论内容有敏感词，评论失败");
            // mongodb添加数据
            mongoTemplate.save(apComment);
            // kafka发送消息，修改aparticle中的数据
            UpdateArticleMess updateArticleMess = new UpdateArticleMess();
            updateArticleMess.setArticleId(dto.getArticleId());
            updateArticleMess.setType(UpdateArticleMess.UpdateArticleType.COMMENT);
            updateArticleMess.setAdd(1);
            // 发送信息，数据聚合
            kafkaTemplate.send(HotArticleConstants.HOT_ARTICLE_SCORE_TOPIC,
                    JSON.toJSONString(updateArticleMess));
        }
        // 返回结果
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 判断文章是否可以评论
     *
     * @param articleId
     * @return
     */
    private boolean checkComment(Long articleId) {
        // 默认为true
        boolean flag = true;
        ResponseResult responseResult = articleClient.getArticleConfig(articleId);
        if (responseResult.getCode().equals(200)) {
            String json = JSON.toJSONString(responseResult.getData());
            ApArticleConfig apArticleConfig = JSON.parseObject(json, ApArticleConfig.class);
            if (!apArticleConfig.getIsComment()) {
                flag = false;
            }
        }
        return flag;
    }

    /**
     * 查询评论列表
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult load(CommentDto dto) {
        // 检查参数
        if (dto == null || dto.getArticleId() == null) {
            throw new CustomException(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        // 判断用户是否登录
        ApUser apUser = AppThreadLocalUtil.getUser();
        if (apUser == null) {
            throw new CustomException(AppHttpCodeEnum.NEED_LOGIN);
        }
        // 分页条件查询
        List<ApComment> apComments =
                mongoTemplate.find(Query.query(Criteria.where("entryId").is(dto.getArticleId())
                                .and("createdTime").lt(dto.getMinDate()))
                        .limit(10)
                        .with(Sort.by(Sort.Direction.DESC, "likes","createdTime")),
                        ApComment.class);
        // 查询当前评论中哪些数据被点赞了
        // 获取评论id集合
        List<String> idList = apComments.stream()
                .map(ApComment::getId)
                .collect(Collectors.toList());
        // 查询评论点赞的集合
        List<ApCommentLike> apCommentLikes = mongoTemplate.find(Query.query(Criteria.where(
                        "authorId").is(apUser.getId())
                .and("commentId").in(idList)), ApCommentLike.class);
        // 集合为空，直接返回
        if (CollectionUtils.isEmpty(apCommentLikes)) {
            return ResponseResult.okResult(apComments);
        }
        // 点赞了，循环，封装ApCommentVo并返回
        List<ApCommentVo> apCommentVos = apComments.stream().map(apComment -> {
            ApCommentVo apCommentVo = new ApCommentVo();
            BeanUtils.copyProperties(apComment, apCommentVo);
            apCommentVo.setOperation((short) 0);
            return apCommentVo;
        }).collect(Collectors.toList());
        // 结果返回
        return ResponseResult.okResult(apCommentVos);
    }

    /**
     * 点赞评论
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult like(CommentLikeDto dto) {
        // 参数检验
        if (dto == null || dto.getCommentId() == null || dto.getOperation() == null) {
            throw new CustomException(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        // 判断用户是否登录
        ApUser apUser = AppThreadLocalUtil.getUser();
        if (apUser == null) {
            throw new CustomException(AppHttpCodeEnum.NEED_LOGIN);
        }
        // 查询 ApComment
        ApComment apComment = mongoTemplate.findById(dto.getCommentId(), ApComment.class);
        // 数据不存在
        if (apComment == null) {
            throw new CustomException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        // 点赞
        if (dto.getOperation() == 0) {
            // ap_comment_like中新增数据
            ApCommentLike apCommentLike = new ApCommentLike();
            apCommentLike.setAuthorId(apUser.getId());
            apCommentLike.setCommentId(dto.getCommentId());
            mongoTemplate.save(apCommentLike);
            // ap_comment中的like加1
            apComment.setLikes(apComment.getLikes() + 1);
        } else if (dto.getOperation() == 1) {
            // 取消点赞
            // ap_comment_like中删除数据
            mongoTemplate.remove(Query.query(Criteria.where("commentId").is(dto.getCommentId())),
                    ApCommentLike.class);
            // ap_comment中的like减1
            apComment.setLikes(apComment.getLikes() - 1);
        }
        // 修改 ApComment
        mongoTemplate.save(apComment);
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 审核评论内容
     *
     * @param text
     * @return
     */
    private boolean autoExamineText(String text) {
        // 默认为审核通过
        boolean flag = true;
        // 文本内容为空，直接返回
        if (text.length() == 0) {
            return flag;
        }
        try {
            // 调用百度云审核文本
            Map textMap = examineUtil.textExamine(text);
            if (textMap != null) {
                // 审核失败
                if (textMap.get("code").equals("block")) {
                    flag = false;
                }
            }
        } catch (Exception e) {
            flag = false;
            e.printStackTrace();
        }
        return flag;
    }
}
